var assert = require("assert")
var test = exports
require("arrayUtils")

test.run = function(t) {
	if (typeof t == "function") {
		try {
			t()
			return {"ok":true}
		} catch(e) {
			if (e instanceof assert.AssertionError) {
				return {"fail":e}
			}
			return {"error":e}
		}
	}
	
	var result = {}
	for (var member in t) {
		if( /^test.*/.test(member) ) {
			result[member] = test.run(t[member])
		}
	}
	
	return result
}

var countResults = function(testResult, count) {
	if (!count) {
		count = {"ok": 0, "fail": 0, "error":0}
	}	
	["ok", "fail", "error"].forEach( function(state) {
		if (testResult[state]) {
			count[state] += 1
		}
	})

	for (var member in testResult) {
		if( /^test.*/.test(member) ) {
			count = countResults(testResult[member], count)
		}
	}
	
	return count
}

var filterResultByState = function(testResult, state) {
	if (testResult[state]) {
		return testResult
	}
	
	var result = null
	for (var member in testResult) {
		if( /^test.*/.test(member) ) {
			var inner = filterResultByState(testResult[member], state)
			if( inner ) {
				result = result || {}
				result[member] = inner
			}
		}
	}
	return result
}

var do_in_tree = function(depth, obj, callback) {
	for (var i in obj) {
		var o = obj[i]
		if (callback(o,i,depth+1) && (o instanceof Object)) {
			do_in_tree(depth + 1, o, callback)
		}
	}
}

var showFailures = function(testResult, console) {
	var filtered = filterResultByState(testResult, "fail")
	console.println("Failures:")
	do_in_tree(0, filtered, function(value, key, depth) {
		var rv = true
		var line = ""
		for( var i=0; i<depth; i++ ) {line += "  "}
		line += key
		if (key == "fail") {
			line += ":" + value.message
			rv = false
		}
		console.println(line)
		return rv
	})
}

var showErrors = function(testResult, console) {
	var filtered = filterResultByState(testResult, "error")
	console.println("Errors:")
	do_in_tree(0, filtered, function(value, key, depth) {
		var rv = true
		var line = ""
		for( var i=0; i<depth; i++ ) {line += "  "}
		line += key
		if (key == "error") {
			line += ":" + value
			rv = false
		}
		console.println(line)
		return rv
	})
}

test.showInConsole = function(testResult, console) {
	console = console || require("console")
	
	var count = countResults(testResult)
	console.println("Tests OK: "+ count.ok)
	console.println("Assertions failed: "+ count.fail)
	console.println("Errors raised: "+ count.error)
	
	if ( count.fail > 0 ) {
		showFailures(testResult, console)
	}
	
	if ( count.error > 0 ) {
		showErrors(testResult, console)
	}
}